/**
 * Created with IntelliJ IDEA.
 * User: ajhin
 * Date: 4/18/13
 * Time: 9:52 PM
 * To change this template use File | Settings | File Templates.
 */
package societyGames.xmlFragment
{
import mx.collections.ArrayCollection;
import mx.collections.IList;

public class XMLFragmentCollection extends ArrayCollection
{
  protected var _xmlContainer:XMLContainer;
  protected var _childClass:Class;
  private var _parentXML:XML;
  private var _childName:String;

  public function initialize(xmlContainer:XMLContainer, parentXML:XML, childClass:Class, childName:String):void
  {
    if (parentXML == null)
    {
      throw new ArgumentError("Argument xml cannot be null.");
    }
    if (childName == null)
    {
      throw new ArgumentError("Argument childName cannot be null.");
    }
    _xmlContainer = xmlContainer;
    _childClass = childClass;
    _parentXML = parentXML;
    _childName = childName;
    var existingFragments:Array = [];
    for each (var childXML:XML in parentXML[_childName])
    {
      existingFragments.push(xmlContainer.createChildXMLFragment(_childClass, childXML));
    }
    this.source = existingFragments;
  }

  private function validateXMLFragment(xmlFragment:XMLFragment):void
  {
    if (xmlFragment.xml.name() != _childName)
    {
      throw new ArgumentError("xmlFragment.xml.name() of " + xmlFragment.xml.name() + " is not expected " + _childName);
    }
  }

  /*private function addXML(xmlFragment:XMLFragment):void
   {
   //TODO: Validate XML Fragment here! Is this duplication of addXMLAt?
   _parentXML.appendChild(xmlFragment.xml);
   }*/

  private function addXMLAt(xmlFragment:XMLFragment, index:int):void
  {
    //TODO: Validate XMLFragment here!
    var existingXMLList:XMLList = _parentXML[xmlFragment.xml.name()];
    if (index < 0 || index > existingXMLList.length())
    {
      throw new RangeError("Invalid range.");
    }
    if (existingXMLList.length() == 0)
    {
      _parentXML.appendChild(xmlFragment.xml);
    }
    else
    {
      if (index == 0)
      {
        _parentXML.insertChildBefore(existingXMLList[0], xmlFragment.xml);
      }
      else
      {
        _parentXML.insertChildAfter(existingXMLList[index - 1], xmlFragment.xml);
      }
    }
  }

  private static function removeXML(xml:XML):void
  {
    delete xml.parent().children()[xml.childIndex()];
  }

  override public function addAll(addList:IList):void
  {
    var index:int;
    for (index = 0; index < addList.length; index++)
    {
      validateXMLFragment(XMLFragment(addList.getItemAt(index)));
    }
    /*for (index = 0; index < addList.length; index++)
     {
     addXML(XMLFragment(addList.getItemAt(index)));
     }*/
    super.addAll(addList);
  }

  override public function addAllAt(addList:IList, index:int):void
  {
    var fragmentIndex:int;
    for (fragmentIndex = 0; fragmentIndex < addList.length; fragmentIndex++)
    {
      validateXMLFragment(XMLFragment(addList.getItemAt(fragmentIndex)));
    }
    /*var xmlIndex:int = index;
     for (fragmentIndex = 0; fragmentIndex < addList.length; fragmentIndex++)
     {
     addXMLAt(XMLFragment(addList.getItemAt(fragmentIndex)), xmlIndex);
     xmlIndex++;
     }*/
    super.addAllAt(addList, index);
  }

  override public function addItem(item:Object):void
  {
    /*var xmlFragment:XMLFragment = XMLFragment(item);
     validateXMLFragment(xmlFragment);
     addXML(xmlFragment);*/
    super.addItem(item);
  }

  override public function addItemAt(item:Object, index:int):void
  {
    var xmlFragment:XMLFragment = XMLFragment(item);
    validateXMLFragment(xmlFragment);
    addXMLAt(xmlFragment, index);
    super.addItemAt(item, index);
  }

  override public function removeAll():void
  {
    var childrenXMLList:XMLList = _parentXML[_childName];
    for each (var childXML:XML in childrenXMLList)
    {
      removeXML(childXML);
    }
    super.removeAll();
  }

  override public function removeItemAt(index:int):Object
  {
    var existingXMLList:XMLList = _parentXML[_childName];
    if (index < 0 || index >= existingXMLList.length())
    {
      throw new RangeError("Invalid range.");
    }
    removeXML(existingXMLList[index]);
    return super.removeItemAt(index);
  }

  override public function setItemAt(item:Object, index:int):Object
  {
    var existingXMLList:XMLList = _parentXML[_childName];
    if (index < 0 || index >= existingXMLList.length())
    {
      throw new RangeError("Invalid range.");
    }
    var xmlFragment:XMLFragment = XMLFragment(item);
    validateXMLFragment(xmlFragment);

    removeItemAt(index);
    addItemAt(xmlFragment, index);
    return super.setItemAt(item, index);
  }
}
}
